package com.deyinet.bdcms.tools;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * Created by Bacel on 2017/4/18.
 */
public class MD5ArithmeticUtils {
    private volatile static MessageDigest messageDigestMD5 = null;

    /**
     * 构造器
     */
    private MD5ArithmeticUtils(){}
    /**
     * 获取MD5
     * <br>Created 2014-8-22 下午4:08:07
     * @param url 源url
     * @return 返回MD5
     */
    public static synchronized String getMd5(String url) {
        if (url == null) {
            url = "";
        }
        if(messageDigestMD5 == null){
            try {
                messageDigestMD5 = MessageDigest.getInstance("MD5");
            } catch (NoSuchAlgorithmException e) {
                throw new RuntimeException("No MD5 algorithm.");
            }
        }
        try {
            messageDigestMD5.update(url.getBytes("UTF-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            messageDigestMD5.update(url.getBytes(Charset.defaultCharset()));
        }
        return getHashString(messageDigestMD5).toUpperCase();
    }

    /**
     * 获取Hash字符串
     * <br>Created 2014-8-22 下午4:09:12
     * @param digest MessageDigest对象
     * @return Hash字符串
     */
    private static String getHashString(MessageDigest digest) {
        StringBuilder builder = new StringBuilder();
        for (byte b : digest.digest()) {
            builder.append(Integer.toHexString((b >> 4) & 0xf));
            builder.append(Integer.toHexString(b & 0xf));
        }
        return builder.toString();
    }

    /**
     * 对字节数组计算md5
     * <br>Created 2014-8-22 下午4:16:13
     * @param buffer 字节数组
     * @return 字节数组的md5
     */
    public static String getMD5OfBytes(byte[] buffer) {
        StringBuffer result = new StringBuffer();
        if (messageDigestMD5 == null) {
            try {
                messageDigestMD5 = MessageDigest.getInstance("MD5");
            } catch (NoSuchAlgorithmException e) {
                throw new RuntimeException("No MD5 algorithm.");
            }
        }
        byte[] b = messageDigestMD5.digest(buffer);
        for (int i = 0; i < b.length; i++) {
            result.append(Integer.toString((b[i] & 0xff) + 0x100, 16)
                    .substring(1));
        }
        return result.toString();
    }

    /**
     * 计算文件的MD5
     * <br>Created 2014-8-22 下午4:29:54
     * @param file 文件对象
     * @return 文件的MD5
     * @throws IOException
     */
    public static synchronized String getFileEncryptString(File file) throws IOException {
        if (messageDigestMD5 == null) {
            try {
                messageDigestMD5 = MessageDigest.getInstance("MD5");
            } catch (NoSuchAlgorithmException e) {
                throw new RuntimeException("No MD5 algorithm.");
            }
        }
        FileInputStream in = new FileInputStream(file);
        FileChannel ch = in.getChannel();
        MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
        in.close();
        messageDigestMD5.update(byteBuffer);
        return getHashString(messageDigestMD5);
    }
}
